/*
 * Copyright 2011 Fabian Wenzelmann
 * 
 * This file is part of Recognition-Procedures-for-Boolean-Functions.
 * 
 * Recognition-Procedures-for-Boolean-Functions is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Recognition-Procedures-for-Boolean-Functions is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Recognition-Procedures-for-Boolean-Functions.  If not, see <http://www.gnu.org/licenses/>.
 */

package de.wenzelmf.booleanFunction.lpb.combinatorial.solver;

import de.wenzelmf.booleanFunction.lpb.combinatorial.splittingTree.SplittingTree;
import de.wenzelmf.booleanFunction.util.IntegerValue;

/**
 * An implementation of {@link CoefficientChooser} that chooses the value as small as possible.
 * 
 * Note that this implementation in combination with {@link ClassicalTreeSolver} turned out
 * to be incomplete! See the paper by Jan-Georg Smaus, Christian Schilling and Fabian
 * Wenzelmann to the ISAIM 2012
 * (<a href="http://www.cs.uic.edu/pub/Isaim2012/WebPreferences/ISAIM2012_Boolean_Schilling_etal.pdf">here</a>).
 * 
 * @author Fabian Wenzelmann
 * @version 1.0
 *
 */
public class MinimumChooser implements CoefficientChooser
{
	
	/**
	 * Constructs a new minimum chooser.
	 */
	public MinimumChooser()
	{
		;
	}

	/**
	 * Returns the smallest possible value a<sub>k</sub> s.t. a &lt; a<sub>k</sub> &lt; b.
	 * 
	 * @return The smallest value a<sub>k</sub> s.t. a &lt; a<sub>k</sub> &lt; b.
	 * 
	 * @throws CoefficientSelectionException If one of {@code a, b} represents {@code NaN}
	 * (should never happen) or if a &ge; b.
	 */
	@Override
	public int chooseCoefficient(IntegerValue a, IntegerValue b, SplittingTree t, int k)
			throws CoefficientSelectionException
	{
		if(a.isNaN() || b.isNaN())
		{
			throw new CoefficientSelectionException("One of the two integer values is NaN");
		}
		if(a.compareTo(b) >= 0)
		{
			throw new CoefficientSelectionException(a, b);
		}
		
		if(a.isNegativeInfinity())
		{	
			if(b.isPositiveInfinity())
			{
				return 0;
			}
			else
			{
				return  b.intValue() - 1;
			}
		}
		else if(a.isPositiveInfinity())
		{
			throw new CoefficientSelectionException(a, b);
		}
		else
		{
			// s is a number
			if(b.isPositiveInfinity())
			{
				return a.intValue() + 1;
			}
			else if(b.isNegativeInfinity())
			{
				throw new CoefficientSelectionException(a, b);
			}
			else
			{
				// both are numbers
				int number1 = a.intValue();
				int number2 = b.intValue();
				int smallestSol = number1 + 1;
				if(!(smallestSol < number2))
				{
					throw new CoefficientSelectionException(a, b);
				}
				else
				{
					return smallestSol;
				}
			}
		}
	}

}
